"""
Case Type   : GUC
Case Name   : listen_addresses参数使用gs_guc reload设置不生效（单节点与多节点）
Create At   : 2021/02/24
Owner       : opentestcase052
Description :
    1、查看listen_addresses默认值
        source [环境变量路径]
        gs_guc check -D [数据库实例路径] -c listen_addresses
    2、使用设置gs_guc reload设置listen_addresses，以'55.66.77.88'为例
        单机（单节点）：
        gs_guc reload -D [数据库实例路径] -c "listen_addresses='55.66.77.88'"
        主备（多节点）：
        gs_guc reload -N all -D [数据库实例路径] -c "listen_addresses='55.66.77.88'"
    3、在配置文件中查看listen_addresses是否为'55.66.77.88'
        cat [数据库实例路径]/postgresql.conf | grep listen_addresses
    4、查看数据库状态验证是否生效
        gs_om -t status --detail
    5、恢复默认值，在各节点执行以下命令
        gs_guc set -D [数据库实例路径] -c "listen_addresses=[各节点默认值]"
Expect      :
    1、查看listen_addresses默认值成功；
    2、gs_guc reload设置listen_addresses，单节点成功，多节点报错；
    3、单节点postgresql.conf中listen_addresses的值和第2步设置的值一样；
    4、查看数据库状态正常，符合预期；
    5、恢复默认值成功
History     : 2021/8/18 为适配listen_addresses默认值变更，修改正则写法
"""
import os
import re
import time
import unittest

from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

logger = Logger()
db_user_list = ['PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser']
primary_sh = CommonSH(db_user_list[0])


@unittest.skipIf(1 == primary_sh.get_node_num(),
                 "当前门禁不支持一主多备用例")
class GucReloadListenAddresses(unittest.TestCase):
    def setUp(self):
        logger.info(f"-----{os.path.basename(__file__)} start-----")
        # 查看数据库状态是否正常
        db_status = primary_sh.get_db_cluster_status("status")
        if not db_status:
            logger.info("The status of db cluster is abnormal. Please check! \
                        db_status: {}".format(db_status))
            self.assertTrue(db_status)

        self.DB_INSTANCE_PATH = macro.DB_INSTANCE_PATH
        self.constant = Constant()
        self.node_list = [Node(x) for x in db_user_list]
        self.commonsh_list = [CommonSH(x) for x in db_user_list]

        # 1、查看listen_addresses默认值，获取默认值
        logger.info("在各节点查看listen_addresses默认值")
        parameter = "listen_addresses"
        strs = self.commonsh_list[0].execute_gsguc(command="check",
                                                   assert_flag="",
                                                   param=parameter,
                                                   get_detail=True)
        str_list = strs.split("\n")
        logger.info(str_list)
        self.default_ips_list = []
        # 举个例子listen_addresses='localhost,192.168.0.100'
        reg1 = re.compile(r"(?<=listen_addresses=')\w{9},\d+\.\d+\.\d+\.\d+|$")
        for string in str_list:
            default_ip_list = reg1.findall(string)
            if default_ip_list and default_ip_list[0]:
                default_ip = "\'{}\'".format(default_ip_list[0])
                self.default_ips_list.append(default_ip)
        if not self.default_ips_list:
            raise Exception("listen_addresses默认值获取为空，请检查")
        logger.info("各节点查看listen_addresses默认值列表:"
                    "{}".format(self.default_ips_list))

    def test_guc_reload_listen_addresses(self):
        # 2、使用设置gs_guc reload设置listen_addresses，指定other_ip为修改值
        other_ip = "\'55.66.77.88\'"
        logger.info(f"指定ip {other_ip} 为修改值")
        # 2.1 单节点
        logger.info("在单节点使用reload设置listen_addresses")
        parameter1 = f"listen_addresses={other_ip}"
        body1 = self.commonsh_list[0].execute_gsguc(command="reload",
                                                    assert_flag="",
                                                    param=parameter1,
                                                    get_detail=True,
                                                    single=True)
        logger.info(body1)
        self.assertIn(self.constant.GSGUC_SUCCESS_MSG, body1)
        logger.info("查看postgresql.conf的值是否和修改值一致")
        command1 = f"cat {self.DB_INSTANCE_PATH}/postgresql.conf " \
                   f"| grep listen_addresses"
        body2 = self.node_list[0].sh(command1).result()
        logger.info(body2)
        reg2 = re.compile(r"\'\d+\.\d+\.\d+\.\d+\'")
        postgresql_listen_addersses = reg2.findall(body2)
        if postgresql_listen_addersses:
            self.assertEqual(postgresql_listen_addersses[0], other_ip,
                             msg=f"gs_guc reload失败，两个ip不一样"
                                 f"{postgresql_listen_addersses[0]},"
                                 f"{other_ip}")
        else:
            raise Exception("postgressql.conf中listen_addresses为空")
        logger.info("postgressql.conf中listen_addresses和修改值一致")
        logger.info("查看数据库状态是否正常")
        time.sleep(5)
        if not self.commonsh_list[0].get_db_cluster_status("status"):
            raise Exception("reload默认值为其他ip后，数据库状态不正常，请检查！")
        logger.info("将listen_addresses还原为为默认ip")
        parameter2 = f"listen_addresses={self.default_ips_list[0]}"
        body3 = self.commonsh_list[0].execute_gsguc(command="set",
                                                    assert_flag="",
                                                    param=parameter2,
                                                    get_detail=True,
                                                    single=True)
        logger.info(body3)
        self.assertIn(self.constant.GSGUC_SUCCESS_MSG, body3)
        logger.info("在单节点使用reload设置listen_addresses完成")
        # 2.2 多节点
        logger.info("在多节点使用reload设置listen_addresses")
        body4 = self.commonsh_list[0].execute_gsguc(command="reload",
                                                    assert_flag="",
                                                    param=parameter1,
                                                    get_detail=True)
        logger.info(body4)
        einfo = 'ERROR: "listen_addresses" can not "reload" with "all" method'
        self.assertIn(einfo, body4)
        logger.info("在多节点使用reload设置listen_addresses完成")

    def tearDown(self):
        logger.info("---------------------清理环境--------------------------")
        if self.default_ips_list:
            logger.info("将listen_addresses还原为为默认ip")
            for j in range(len(self.commonsh_list)):
                parameter3 = f"listen_addresses={self.default_ips_list[j]}"
                body6 = self.commonsh_list[j].execute_gsguc(command="set",
                                                            assert_flag="",
                                                            param=parameter3,
                                                            get_detail=True,
                                                            single=True)
                logger.info(body6)
                self.assertIn(self.constant.GSGUC_SUCCESS_MSG, body6)
            restart_res = self.commonsh_list[0].restart_db_cluster()
            self.assertTrue(restart_res, '重启集群失败')
        logger.info(f"-----{os.path.basename(__file__)} end-----")
